/// 
/// MaDAson - Toolkit for Model Driven Software Development
/// 
/// Copyright [2006] Marcus Lankenau
/// 
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///  
///     http://www.apache.org/licenses/LICENSE-2.0
///  
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// 

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.CodeDom.Compiler;
using System.Collections;

namespace Madason.TemplateCompiler
{
	class Program
	{
		private static string ExtractClassName(string path)
		{
			int pos1 = path.LastIndexOf("\\");
			int pos2 = path.LastIndexOf(".");

			return path.Substring(pos1 + 1, pos2 - pos1 - 1);			
		}

		public static void GenerateClass(string inputPath, string targetPath)
		{
			ClassGeneratorCsharp gen = new ClassGeneratorCsharp();
			gen.ClassName = ExtractClassName(inputPath);
			StreamReader reader = new StreamReader(inputPath);
			StreamWriter writer = new StreamWriter(targetPath);
			gen.Generate(reader, writer);
			writer.Flush();
			writer.Close();
			reader.Close();
		}


		public static string GenerateClass(string inputPath)
		{
			StringWriter stringWriter = new StringWriter();
			ClassGeneratorCsharp gen = new ClassGeneratorCsharp();
			gen.ClassName = ExtractClassName(inputPath);
			StreamReader reader = new StreamReader(inputPath);
			gen.Generate(reader, stringWriter);
			reader.Close();
			stringWriter.Flush();
			return stringWriter.ToString();
		}



		protected static List<FileInfo> GetFilesDeep(DirectoryInfo dir)
		{
			List<FileInfo> results = new List<FileInfo>();

			foreach (FileInfo file in dir.GetFiles())
				results.Add(file);
			
			foreach (DirectoryInfo subdir in dir.GetDirectories())
			{
				results.AddRange(GetFilesDeep(subdir));
			}
			return results;
		}

		public static int Generate(DirectoryInfo dir, string[] references, string targetName)
		{
			DirectoryInfo tempdir = new DirectoryInfo("tc_temp");
			tempdir.Create();
			

			List<string> sourceTextNames = new List<string>();

			CompilerParameters options = new CompilerParameters();

			foreach (FileInfo file in GetFilesDeep(dir))
			{
				if (file.Extension.ToLower() == ".aspx")
				{
					string targetPath = tempdir.FullName + "\\" + file.Name;
					GenerateClass(file.FullName, targetPath);
					sourceTextNames.Add(targetPath);
				}
				if (file.Extension.ToLower() == ".cs")
				{
					sourceTextNames.Add(file.FullName);
				}
				if (file.Extension.ToLower() == ".xml")
				{
					options.EmbeddedResources.Add(file.FullName);
				}
			}

			
			options.GenerateExecutable = true;
			options.OutputAssembly = targetName;
			options.CompilerOptions = "/debug";
			options.ReferencedAssemblies.Add("System.dll");
			options.ReferencedAssemblies.Add("System.Xml.dll");
			foreach (string reference in references)
				options.ReferencedAssemblies.Add(reference);	
			Microsoft.CSharp.CSharpCodeProvider comp = new Microsoft.CSharp.CSharpCodeProvider();

			CompilerResults results = comp.CompileAssemblyFromFile(options, sourceTextNames.ToArray());
			foreach (CompilerError error in results.Errors)
			{
				Console.Out.WriteLine("error: " + error.ErrorText + " (" + error.FileName+ ":"  + error.Line + ")");
			}
			return results.Errors.Count;
			//tempdir.Delete(true);
		}


		
		static int Main(string[] args)
		{
			if (args.Length == 0)
			{
				Console.Out.WriteLine("usage: templatecompiler.exe templatepath references=assembly1.dll,assembly2.dll [targetName=somename.exe]");
				return -1;
			}

			Hashtable paramMap = new Hashtable();

			string templatePath = args[0];
			foreach (string arg in args)
			{
				string[] parts = arg.Split("=".ToCharArray());
				if (parts.Length == 2)
				{
					paramMap[parts[0]] = parts[1];
				}
			}

			string[] references = new string[0];
			if (paramMap.ContainsKey("references"))
			{
				string referencesParam = paramMap["references"] as string;
				references = referencesParam.Split(",".ToCharArray());
			}

			string targetName = "mda.exe";
			if (paramMap.ContainsKey("targetName"))
			{
				targetName = paramMap["targetName"] as string;
			}
			
			
			return Generate(new DirectoryInfo(templatePath),references, targetName);
		}
	}
}
